package sgsi.model.entidades.espacios;
import java.util.HashSet;
import java.util.Set;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;

import sgsi.model.entidades.Articulo;
import sgsi.model.entidades.Cliente;
import sgsi.model.entidades.Prioridad;
import sgsi.model.entidades.RangoDeTemperatura;
import sgsi.model.entidades.TipoDeArticulo;
import sgsi.model.entidades.auxiliares.BorradoLogico;

public class Area extends BorradoLogico {

	private int codigoArea;
	private boolean accesoRestringido;
	private boolean bajoTecho;
	private String nombre;
	private Set<Area> areasAdyacentes;
	private Set<Ubicacion> ubicaciones;
	private Set<TipoDeArticulo> tipoDeArticulosSoportados;
	private RangoDeTemperatura rangoDeTemperatura;
	private Almacen almacen;
	private Prioridad prioridad;

	public Area() {
		areasAdyacentes = new HashSet<Area>();
		tipoDeArticulosSoportados = new HashSet<TipoDeArticulo>();
	}
	
	public Prioridad getPrioridad() {
		return prioridad;
	}

	public void setPrioridad(Prioridad prioridad) {
		this.prioridad = prioridad;
	}

	public boolean isAccesoRestringido() {
		return accesoRestringido;
	}

	public void setAccesoRestringido(boolean accesoRestringido) {
		this.accesoRestringido = accesoRestringido;
	}

	public boolean isBajoTecho() {
		return bajoTecho;
	}

	public void setBajoTecho(boolean bajoTecho) {
		this.bajoTecho = bajoTecho;
	}

	public String getNombre() {
		return nombre;
	}

	public void setNombre(String nombre) {
		this.nombre = nombre;
	}

	public RangoDeTemperatura getRangoDeTemperatura() {
		return rangoDeTemperatura;
	}

	public void setRangoDeTemperatura(RangoDeTemperatura rangoDeTemperatura) {
		this.rangoDeTemperatura = rangoDeTemperatura;
	}

	public void setAlmacen(Almacen almacen) {
		this.almacen = almacen;
	}

	public Almacen getAlmacen() {
		return almacen;
	}

	public boolean soportaAlArticulo(TipoDeArticulo tipoDeArticulo) {
		if (tipoDeArticulosSoportados == null)
			return false;
			
		return tipoDeArticulosSoportados.contains(tipoDeArticulo);
	}

	public boolean puedeAlmacenarA(TipoDeArticulo tipoDeArticulo) {
		if (!tipoDeArticulo.isAireLibre() && !bajoTecho)
			return false;

		if (tipoDeArticulo.isAccesoRestringido() && !accesoRestringido)
			return false;

		return tipoDeArticulo.getRangoDeTemperatura().equals(rangoDeTemperatura);
	}

	public void setCodigoArea(int codigoArea) {
		this.codigoArea = codigoArea;
	}

	public int getCodigoArea() {
		return codigoArea;
	}

	public void setAreasAdyacentes(Set<Area> areasAdyacentes) {
		this.areasAdyacentes = areasAdyacentes;
	}

	public Set<Area> getAreasAdyacentes() {
		return areasAdyacentes;
	}

	public void setUbicaciones(Set<Ubicacion> ubicaciones) {
		this.ubicaciones = ubicaciones;
	}

	public Set<Ubicacion> getUbicaciones() {
		return ubicaciones;
	}

	public void setTipoDeArticulosSoportados(Set<TipoDeArticulo> tipoDeArticulosSoportados) {
		this.tipoDeArticulosSoportados = tipoDeArticulosSoportados;
	}

	public Set<TipoDeArticulo> getTipoDeArticulosSoportados() {
		return tipoDeArticulosSoportados;
	}
	
	public boolean tienePaletsDelCliente(final Cliente cliente) {
		
		Ubicacion ubicacion = (Ubicacion) CollectionUtils.find(ubicaciones, new Predicate() {
			public boolean evaluate(Object objeto) {
				Ubicacion ubicacion = (Ubicacion) objeto;
					
				return ubicacion.tienePaletsDelCliente(cliente);
			}
		});				
		
		return ubicacion != null;
	}
	
	public boolean tienePaletsDelTipoDeArticulo(final TipoDeArticulo tipoDeArticulo) {
		
		Ubicacion ubicacion = (Ubicacion) CollectionUtils.find(ubicaciones, new Predicate() {
			public boolean evaluate(Object objeto) {
				Ubicacion ubicacion = (Ubicacion) objeto;
				
				return ubicacion.tienePaletsDelTipoDeArticulo(tipoDeArticulo);
			}
		});				
		
		return ubicacion != null;
	}
	
	public boolean tienePaletsDelArticulo(final Articulo articulo) {
		
		Ubicacion ubicacion = (Ubicacion) CollectionUtils.find(ubicaciones, new Predicate() {
			public boolean evaluate(Object objeto) {
				Ubicacion ubicacion = (Ubicacion) objeto;
				
				return ubicacion.tienePaletsDelArticulo(articulo);
			}
		});				
		
		return ubicacion != null;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + codigoArea;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Area other = (Area) obj;
		if (codigoArea != other.codigoArea)
			return false;
		return true;
	}

	@Override
	public boolean puedeSerBorrada() {
		boolean puedoBorrar = true;
		
		for(Ubicacion ubicacion : ubicaciones) {
			puedoBorrar = ubicacion.getEstaBorrado();
			
			if (! puedoBorrar)
				return false;
		}
		
		return puedoBorrar;
	}						

	public void agregarAreaAdyacente(Area areaAdyacente) {
		areasAdyacentes.add(areaAdyacente);		
	}
	
	public void quitarAreasAdyacentes() {
		areasAdyacentes.clear();	
	}

	public void agregarTipoDeArticuloSoportado(TipoDeArticulo tipoDeArticulo) {
		tipoDeArticulosSoportados.add(tipoDeArticulo);		
	}
	
	public void quitarTipoDeArticuloSoportado() {
		tipoDeArticulosSoportados.clear();	
	}

}
